package com.author.document.style;

import java.awt.Font;
import java.util.HashMap;
import java.util.Map;

import javax.swing.text.AttributeSet;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;

/**
 * This class maintains the style to attribute mapping. All styles are defined
 * here and they are associated with their associated attribute values.
 * 
 * Addition of new styles, addition of new attributes to existing style, removal
 * of styles and attributes associated with styles will be performed here.
 */
public final class ExtendedDefaultStyleContext extends StyleContext {
	/** Style name to actual style mapping */
	public static Map<String, Style>	mapStyleNameToLogicalStyle	= new HashMap<String, Style>();

	public ExtendedDefaultStyleContext() {
		String[] stylename = DefaultStyleConstant.getAllStyles();

		// if no styles are currently defined then add normal style
		if ((stylename == null) || (stylename.length <= 0)) {
			addStyle(DefaultStyleConstant.NORMAL_STYLE, null);
			Style normalStyle = getStyle(DefaultStyleConstant.NORMAL_STYLE);

			// Add attributes for normal style
			StyleConstants.setAlignment(normalStyle, StyleConstants.ALIGN_LEFT);
			StyleConstants.setFontFamily(normalStyle,
					DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
			StyleConstants.setFontSize(normalStyle,
					DefaultStyleConstant.NORMAL_STYLE_FONT_SIZE);
			mapStyleNameToLogicalStyle.put(DefaultStyleConstant.NORMAL_STYLE,
					normalStyle);
		}
		init(stylename);
	}

	/**
	 * Add all the defined constant styles to style context
	 */
	private void init(String[] stylename) {
		int len = stylename.length;

		for (int i = 0; i < len; i++) {
			if (stylename[i].equals(DefaultStyleConstant.HEADING_1_STYLE)) {
				// Add "Heading 1" style
				Style heading1Style = addStyle(
						DefaultStyleConstant.HEADING_1_STYLE, null);

				// Add all attributes associated with "Heading 1" style
				StyleConstants.setAlignment(heading1Style,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(heading1Style,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(heading1Style,
						DefaultStyleConstant.HEADING_1_STYLE_FONT_SIZE);
				StyleConstants.setBold(heading1Style, true);
				mapStyleNameToLogicalStyle.put(stylename[i], heading1Style);
				continue;
			}

			if (stylename[i].equals(DefaultStyleConstant.HEADING_2_STYLE)) {
				// Add "Heading 2" style
				Style heading2Style = addStyle(
						DefaultStyleConstant.HEADING_2_STYLE, null);

				// Add all attributes associated with "Heading 2" style
				StyleConstants.setAlignment(heading2Style,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(heading2Style,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(heading2Style,
						DefaultStyleConstant.HEADING_2_STYLE_FONT_SIZE);
				StyleConstants.setBold(heading2Style, true);
				mapStyleNameToLogicalStyle.put(stylename[i], heading2Style);
				continue;
			}

			if (stylename[i].equals(DefaultStyleConstant.HEADING_3_STYLE)) {
				Style heading3Style = addStyle(
						DefaultStyleConstant.HEADING_3_STYLE, null);

				StyleConstants.setAlignment(heading3Style,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(heading3Style,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(heading3Style,
						DefaultStyleConstant.HEADING_3_STYLE_FONT_SIZE);
				StyleConstants.setBold(heading3Style, true);
				mapStyleNameToLogicalStyle.put(stylename[i], heading3Style);
				continue;
			}

			if (stylename[i].equals(DefaultStyleConstant.HEADING_4_STYLE)) {
				Style heading4Style = addStyle(
						DefaultStyleConstant.HEADING_4_STYLE, null);

				StyleConstants.setAlignment(heading4Style,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(heading4Style,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(heading4Style,
						DefaultStyleConstant.HEADING_4_STYLE_FONT_SIZE);
				StyleConstants.setBold(heading4Style, true);
				mapStyleNameToLogicalStyle.put(stylename[i], heading4Style);
				continue;
			}

			if (stylename[i].equals(DefaultStyleConstant.NORMAL_STYLE)) {
				// Add "Normal" style
				Style normalStyle = addStyle(DefaultStyleConstant.NORMAL_STYLE,
						null);

				// Add all attributes associated with "Normal" style
				StyleConstants.setAlignment(normalStyle,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(normalStyle,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(normalStyle,
						DefaultStyleConstant.NORMAL_STYLE_FONT_SIZE);
				mapStyleNameToLogicalStyle.put(stylename[i], normalStyle);
				continue;
			}

			if (stylename[i].equals(DefaultStyleConstant.PARAGRAPH_STYLE)) {
				// Add "Paragraph" style
				Style paragraphStyle = addStyle(
						DefaultStyleConstant.PARAGRAPH_STYLE, null);

				// Add all attributes associated with "Paragraph" style
				StyleConstants.setAlignment(paragraphStyle,
						StyleConstants.ALIGN_LEFT);
				StyleConstants.setFontFamily(paragraphStyle,
						DefaultStyleConstant.DEFAULT_STYLE_FONT_NAME);
				StyleConstants.setFontSize(paragraphStyle,
						DefaultStyleConstant.PARAGRAPH_STYLE_FONT_SIZE);
				mapStyleNameToLogicalStyle.put(stylename[i], paragraphStyle);
				continue;
			}
		}
	}

	/**
	 * Get the default style, which will be the "Normal" style
	 */
	public Style getDefaultStyle() {
		return mapStyleNameToLogicalStyle
				.get(DefaultStyleConstant.DEFAULT_STYLE);
	}

	/**
	 * Get style corresponding to the name of the style in string format
	 */
	public Style getStyle(String stylename) {
		/*
		 * If the style name is null then return the default style, which will
		 * be the normal style
		 */
		if ((stylename == null) || (stylename == "")) {
			return mapStyleNameToLogicalStyle
					.get(DefaultStyleConstant.DEFAULT_STYLE);
		}
		Object o = (Style) mapStyleNameToLogicalStyle.get(stylename);
		return (Style) ((o == null) ? mapStyleNameToLogicalStyle
				.get(DefaultStyleConstant.NORMAL_STYLE) : o);
	}

	@Override
	public Style addStyle(String stylename, Style style) {
		return super.addStyle(stylename, style);
	}

	/**
	 * Removes a style from the style context object
	 */
	public void removeStyle(String stylename) {

	}

	/**
	 * Update the attribute set associated with a style. The boolean replace
	 * flag will indicate whether the existing attributes will be completely
	 * replaced or merged with the new attributes.
	 */
	public void updateStyle(String stylename, AttributeSet set, boolean replace) {

	}

	/** Add attributes to an existing style */
	public void addAttributes(String stylename, AttributeSet set) {

	}

	/** Remove attributes from an existing style */
	public void removeAttributes(String stylename, AttributeSet set) {

	}
}
